package tool.image;

import java.awt.AWTException;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.swing.ImageIcon;

import struct.PositionColor;
import tool.keep.Keeper;
import tool.keep.Keeper.NumberPoints;
import tool.keep.Keeper.startPosition;
import tool.mouse.MouseTool;
import tool.paoshang.Luxian;
import tool.paoshang.PaoShang;
import tool.windows.User32;
import tool.windows.W32API.HWND;
import tool.windows.struct.LPRECTlpRect;

public class ImageTool {

	public static final char[] HEX_CHAR = {'0', '1', '2', '3', '4', '5', 
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
	public static int xytop = 124 , xybottom = 132;
	public static Point x1top = new Point (43,124);
	public static Point x1bottom = new Point (50,132);
	public static Point x2top = new Point (51,124);
	public static Point x2bottom = new Point (58,132);
	public static Point x3top = new Point (59,124);
	public static Point x3bottom = new Point (66,132);
	public static Point y1top = new Point (84,124);
	public static Point y1bottom = new Point (91,132);
	public static Point y2top = new Point (92,124);
	public static Point y2bottom = new Point (99,132);
	public static Point y3top = new Point (100,124);
	public static Point y3bottom = new Point (107,132);

	public static BufferedImage getScreenImage() {
		Robot robot = null;
		try {
			robot = new Robot();
		} catch (AWTException e) {

			e.printStackTrace();
		}
		BufferedImage bi = robot.createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
		return bi;
	}

	public static BufferedImage getScreenShoot(LPRECTlpRect rect) {
		BufferedImage image = Keeper.getRobot()
				.createScreenCapture(new Rectangle(rect.x, rect.y, rect.width - rect.x, rect.height - rect.y));
		return image;
	}

	public static int[][] getRGBs(BufferedImage image) {
		int[][] data = new int[image.getWidth()][image.getHeight()];
		for (int i = 0; i < image.getWidth(); i++) {
			for (int j = 0; j < image.getHeight(); j++) {
				data[i][j] = image.getRGB(i, j);
			}
		}
		return data;
	}

	public static BufferedImage getScreenShoot(HWND hwnd) {
		LPRECTlpRect rect = getClientRect(hwnd);
		BufferedImage image = Keeper.getRobot()
				.createScreenCapture(new Rectangle(rect.x, rect.y, rect.width - rect.x, rect.height - rect.y));
		return image;
	}

	public static BufferedImage getScreenShoot(HWND hwnd, Point p) {
		LPRECTlpRect rect = getClientRect(hwnd);
		BufferedImage image = Keeper.getRobot()
				.createScreenCapture(new Rectangle(rect.x+p.x, rect.y + p.y, 40, 30));
		return image;
	}
	

	public static BufferedImage getScreenShoot(Point p) {
		BufferedImage image = Keeper.getRobot()
				.createScreenCapture(new Rectangle(p.x, p.y, 120, 110));
		return image;
	}

	public static BufferedImage getScreenShoot(HWND hwnd,LPRECTlpRect rect) {
		LPRECTlpRect clientRect = getClientRect(hwnd);
		LPRECTlpRect picRect = new LPRECTlpRect();
		picRect.x = clientRect.x+rect.x;
		picRect.y = clientRect.y+rect.y;
		picRect.width=rect.width;
		picRect.height=rect.height;
		BufferedImage image = Keeper.getRobot()
				.createScreenCapture(new Rectangle(picRect.x, picRect.y, picRect.width, picRect.height));
		return image;
	}

	public static LPRECTlpRect getClientRect(HWND hwnd) {
		LPRECTlpRect rect = new LPRECTlpRect();
		User32.INSTANCE.GetWindowRect(hwnd, rect);
		return rect;
	}

	public static LPRECTlpRect getPointAroundRect(Point point, int pix) {
		return getPointAroundRect(point, pix, pix);
	}

	public static LPRECTlpRect getPointAfterRect(Point point, int pix) {
		return getPointAfterRect(point, pix, pix);
	}

	private static LPRECTlpRect getPointAfterRect(Point point, int x, int y) {
		LPRECTlpRect rect = new LPRECTlpRect();
		rect.x = point.x;
		rect.y = point.y;
		rect.width = point.x + x;
		rect.height = point.y + y;
		return rect;
	}

	public static LPRECTlpRect getPointAroundRect(Point point, int x, int y) {
		LPRECTlpRect rect = new LPRECTlpRect();
		rect.x = point.x - x / 2;
		rect.y = point.y - y / 2;
		rect.width = point.x + x / 2;
		rect.height = point.y + y / 2;
		return rect;
	}

	public static void saveImage(BufferedImage imageBuff, String fileAdd) {
		File f = new File(fileAdd);
		try {
			ImageIO.write(imageBuff, "jpg", f);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static Point findPoint(BufferedImage image, List<PositionColor> positionColors) {

		Point position = new Point(-1, -1);
		int[][] rgbs = getRGBs(image);
		for (PositionColor positionColor : positionColors) {
			for (int x = 0; x < image.getWidth(); x++) {
				for (int y = 0; y < image.getHeight(); y++) {
					if (rgbs[x][y] == positionColor.getRgb()) {
						boolean conflag = false;
						if (positionColor.getPositionColors() == null) {

						}
						for (PositionColor item : positionColor.getPositionColors()) {
							int _x = item.getX() + x;
							int _y = item.getY() + y;
							if (_x >= image.getWidth() || _y >= image.getHeight()) {
								conflag = true;
								break;
							} else if (rgbs[_x][_y] == item.getRgb()) {
								continue;
							} else {
								conflag = true;
								break;
							}
						}
						if (conflag)
							continue;
						position.x = x;
						position.y = y;
						return position;
					}
				}
			}
		}
		return position;
	}

	public static int RGB2INT(int r, int g, int b) {
		return r * 256 * 256 + g * 256 + b - 16777216;
	}

	public static boolean isSame(BufferedImage image1,BufferedImage image2){
		if(!(image1!=null && image2 != null &&image1.getWidth() == image2.getWidth() && image1.getHeight() == image2.getHeight())){
			return false;
		}
		for (int x = 0; x < image1.getWidth(); x++) {
			for (int y = 0; y < image1.getHeight(); y++) {
				if(image1.getRGB(x, y) != image2.getRGB(x, y)){
					return false;
				}
			}
		}
		return true;
	}

	public static Point findFirstDiff(BufferedImage imageNoMouse,BufferedImage imageMouse){
		for(int y=0;y<imageNoMouse.getWidth();y++){
			for(int x=0;x<imageNoMouse.getWidth();x++){
				if(imageNoMouse.getRGB(x, y) != imageMouse.getRGB(x, y)){
					return new Point(x,y);
				}
			}
		}
		return new Point(-1,-1);
	}

	public static Point getWorldDifferent(HWND hwnd){
		BufferedImage nowImage = getScreenShoot(hwnd);
		return getWorldDifferent(nowImage);
	}

	public static Point getWorldDifferent(BufferedImage image) {

		Integer differentCount = 0;
		for(int y=Keeper.mhTitleHeight;y<Keeper.mhClintSize.y - Keeper.mhBonder;y++){
			for(int x=Keeper.mhBonder;x<Keeper.mhClintSize.x - Keeper.mhBonder;x++){
				if(image.getRGB(x, y)!=Keeper.getWorldNoneChoose().getRGB(x, y) && image.getRGB(x, y)!=Keeper.getWorldAllChoose().getRGB(x, y)){
					int xdiff = 0;
					for(int z=1;z<=5;z++) {
						try {
						if(image.getRGB(x+z, y)!=Keeper.getWorldNoneChoose().getRGB(x+z, y) && image.getRGB(x+z, y)!=Keeper.getWorldAllChoose().getRGB(x+z, y)) {
							xdiff++;
						}
						}catch(ArrayIndexOutOfBoundsException e) {
							y++;
							x=Keeper.mhBonder;
							continue;
						}
					}
					if(xdiff==5) {
						y++;
						x=Keeper.mhBonder;
						continue;
					}
					differentCount = 0;
					for(int i=1;i<10;i++) {
						if(x+1>=Keeper.mhClintSize.y-Keeper.mhBonder || y+1 >= Keeper.mhClintSize.y - Keeper.mhBonder) {
							differentCount++;
						}else {
							try {
								if(image.getRGB(x+i, y+i)!=Keeper.getWorldNoneChoose().getRGB(x+i, y+i) && image.getRGB(x+i, y+i)!=Keeper.getWorldAllChoose().getRGB(x+i, y+i))
								{
									differentCount++;
								}
							}catch(ArrayIndexOutOfBoundsException e) {
								y++;
								x=Keeper.mhBonder;
								continue;
							}
						}
					}
					if(differentCount>7) {
						for(int i=10;i>0;i--) {
							for(int j = 0; j< 10 ;j++){
								if(image.getRGB(x-i, y+j)!=Keeper.getWorldNoneChoose().getRGB(x-i, y+j) && image.getRGB(x-i, y+j)!=Keeper.getWorldAllChoose().getRGB(x-i, y+j)){
									return new Point(x-i+1,y+j+1);
								}
							}
						}
					}
				}
			}
		}
		return new Point(-1,-1);
	}
	
	public static Point imageToLocation(BufferedImage bi) {
		Integer x1 = null;
		Integer x2 = null;
		Integer x3 = null;
		Integer y1 = null;
		Integer y2 = null;
		Integer y3 = null;
		x1 = getNum(bi,startPosition.x1);
		x2 = getNum(bi,startPosition.x2);
		x3 = getNum(bi,startPosition.x3);
		y1 = getNum(bi,startPosition.y1);
		y2 = getNum(bi,startPosition.y2);
		y3 = getNum(bi,startPosition.y3);
		x1*=x2==null?1:10;
		x1*=x3==null?1:10;
		if(x2==null) x2=0;
		x2*=x3==null?1:10;
		if(x3==null) x3=0;
		y1*=y2==null?1:10;
		y1*=y3==null?1:10;
		if(y2==null) y2=0;
		y2*=y3==null?1:10;
		if(y3==null) y3=0;
		return new Point(x1+x2+x3,y1+y2+y3);
	}

	private static Integer getNum(BufferedImage bi,startPosition position) {
		int[] counts = new int[8];
		for(int x=0;x<8;x++) {
			int count=0;
			for(int y=0;y<9;y++) {
				if(bi.getRGB(position.getPosition()+x, y)==-1) 
					count++;
			}
			counts[x] = count;
		}
		for(NumberPoints number:NumberPoints.values()) {
			boolean go = false;
			for(int i=0;i<8;i++) {
				if(number.getWhiteNumber()[i]!=counts[i]) {
					go=true;
					break;
				}
			}
			if(go) {
				continue;
			}
			return number.getNumber();
		}
		return null;
	}

	public static boolean ifCheck(HWND hwnd,Point mouse)  {
		return ifCheck2(hwnd,mouse);
	}

	public static boolean ifCheck2(HWND hwnd,Point mouse)  {
		BufferedImage bi = getScreenShoot(hwnd,new Point(mouse.x+10,mouse.y-15));
		for(int y = 0;y<bi.getHeight();y++) {
			for(int x = 0;x<bi.getWidth();x++) {
				Color c = new Color(bi.getRGB(x, y));
				if(c.getRGB()==new Color(64,108,120).getRGB()) {
					return true;
				}
			}
		}
		
		return false;
	}

	public static boolean ifCheckByRealMouse()  {
		Luxian.sleep(300);
		Point mouse = MouseTool.getMouseRealLocation();
		
		BufferedImage bi = getScreenShoot(new Point(mouse.x-30,mouse.y-55));
		for(int y = 0;y<bi.getHeight();y++) {
			for(int x = 0;x<bi.getWidth();x++) {
				Color c = new Color(bi.getRGB(x, y));
				if(c.getRGB()==new Color(64,108,120).getRGB()) {
					return true;
				}
			}
		}
		
		return false;
	}
}